package com.trainfinder;

import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import java.util.List;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.struts.action.Action;
import org.apache.struts.action.ActionForm;
import org.apache.struts.action.ActionForward;
import org.apache.struts.action.ActionMapping;

import com.trainfinder.database.DateItem;
import com.trainfinder.database.JourneyDetails;
import com.trainfinder.database.JourneyDetailsImpl;
import com.trainfinder.database.Line;
import com.trainfinder.datapersistace.BeanStorage;
import com.trainfinder.datapersistace.BeanStorageFactory;
import com.trainfinder.datapersistace.Journey;
import com.trainfinder.datapersistace.TicketType;

public class SearchAction extends Action {

	private static final long MILISECONDS_IN_A_DAY = 1000 * 60 * 60 * 24;

	private final static Log LOG = LogFactory.getLog(SearchAction.class);

	private final static MonthsImpl MONTHS = new MonthsImpl();

	public ActionForward execute(ActionMapping mapping, ActionForm form,
			HttpServletRequest request, HttpServletResponse response)
			throws IOException, ServletException {
		try {

			SearchActionForm actionForm = (SearchActionForm) form;
			BeanStorage storage = BeanStorageFactory.getInstance();

			
			List<Journey> outwardList = new ArrayList<Journey>();
			List<Journey> returnList = new ArrayList<Journey>();

			List list = null;

			String toLocation = (String) actionForm.getToLocation();
			String fromLocation = (String) actionForm.getFromLocation();
			String monthStr = (String) actionForm.getMonth();
			String day = (String) actionForm.getDay();

			final Calendar calendar = Calendar.getInstance();
			int month = Integer.parseInt(monthStr.substring(0, 2)) - 1;
			int year = 2000 + Integer.parseInt(monthStr.substring(2, 4));

			calendar.set(year, month, Integer.parseInt(day), 0, 0);

			if (calendar.getTime().getTime() < new Date().getTime()) {
				calendar.setTime(new Date());
			}

			LOG.info("Search : day\\month\\year " + day + "\\" + month + "\\"
					+ year);

			list = storage.retreive(calendar.getTime(), fromLocation,
					toLocation, TicketType.valueOf(actionForm.getTicketType()));

			for (Iterator iter = list.iterator(); iter.hasNext();) {
				Journey journey = (Journey) iter.next();

				if (journey.getOutwardOrReturn() == 'O') {
					outwardList.add(journey);
				} else {
					returnList.add(journey);
				}
			}

			int oldDayNumber = -1;
			int outwardDayNumber;
			int returnDayNumber;

			Collection<DateItem> dateItems = new ArrayList<DateItem>();
			request.setAttribute("dateItems", dateItems);
			request.setAttribute("monthsList", MONTHS.getMonths());
			// request.setAttribute("saturdayNight",
			// actionForm.getSaturdayNight());

			Collection<Line> lines = null;
			Iterator outerIter = outwardList.iterator();
			Iterator returnIter = returnList.iterator();

			Journey outwardJourney;
			Journey returnJourney;

			if (outerIter.hasNext()) {
				outwardJourney = (Journey) outerIter.next();
				System.out.println(outwardJourney.toString());
			} else {
				outwardJourney = null;
			}

			if (returnIter.hasNext()) {
				returnJourney = (Journey) returnIter.next();
			} else {
				returnJourney = null;
			}

			// this bit of crazy logic, helps decided what data goes on what
			// line

			do {

				Line line = new Line();

				if (outwardJourney != null) {
					outwardDayNumber = (int) (outwardJourney.id.getDate()
							.getTime() / MILISECONDS_IN_A_DAY);
				} else {
					outwardDayNumber = Integer.MAX_VALUE;
				}

				if (returnJourney != null) {
					returnDayNumber = (int) (returnJourney.id.getDate()
							.getTime() / MILISECONDS_IN_A_DAY);
				} else {
					returnDayNumber = Integer.MAX_VALUE;
				}

				if (outwardDayNumber != oldDayNumber
						&& returnDayNumber != oldDayNumber) {

					if (outwardDayNumber < returnDayNumber) {
						oldDayNumber = outwardDayNumber;
					} else {
						oldDayNumber = returnDayNumber;
					}

					final DateItem dateItem;

					// System.out.println("returnDayNumber" + returnDayNumber);
					if (outwardDayNumber < returnDayNumber) {
						dateItem = new DateItem(outwardJourney.id.getDate());
					} else {
						dateItem = new DateItem(returnJourney.id.getDate());
					}
					dateItems.add(dateItem);

					lines = new ArrayList<Line>();
					dateItem.setLines(lines);

				}

				if (outwardDayNumber == oldDayNumber) {
					JourneyDetails details = new JourneyDetailsImpl(
							outwardJourney, 15000);
					line.setOutwardJourney(details);
					if (outerIter.hasNext()) {
						outwardJourney = (Journey) outerIter.next();
					} else {
						outwardJourney = null;
					}
				}

				if (returnDayNumber == oldDayNumber) {
					JourneyDetails details = new JourneyDetailsImpl(
							returnJourney, 15000);
					line.setReturnJourney(details);
					if (returnIter.hasNext()) {
						returnJourney = (Journey) returnIter.next();
					} else {
						returnJourney = null;
					}
				}

				lines.add(line);
			} while (outerIter.hasNext() || returnIter.hasNext());

		} catch (Throwable t) {

			StringWriter sw = new StringWriter();
			PrintWriter pw = new PrintWriter(sw, true);
			t.printStackTrace(pw);
			pw.flush();
			sw.flush();

			LOG.info("StackTrace :\n" + sw.toString());
		}

		
		return (mapping.findForward("success"));

	}

	public static void main(String args[]) {
		BeanStorage storage = BeanStorageFactory.getInstance();
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(new Date());
		calendar.add(Calendar.DAY_OF_YEAR, -5);
		calendar.getTime();

		List list = storage.retreive(calendar.getTime(), "london", "paris",
				TicketType.NON_FLEXIBLE);

		for (Object object : list) {
			System.out.println(object.toString());
		}
		System.out.println();
	}
}